import com.google.common.io.Files
import com.intellij.database.model.DasTable
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat

/*
 * Available context bindings:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

packageName = "com.sample;"
typeMapping = [
        (~/(?i)int/)                      : "long",
        (~/(?i)float|double|decimal|real/): "double",
        (~/(?i)decimal/): "BigDecimal",
        (~/(?i)datetime|timestamp/)       : "java.sql.Timestamp",
        (~/(?i)date/)                     : "java.sql.Date",
        (~/(?i)time/)                     : "java.sql.Time",
        (~/(?i)/)                         : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) }
}

def generate(table, dir) {
    def className = javaName(table.getName(), true)
    def fields = calcFields(table)
    new File(dir, className + "Controller.java").withPrintWriter { out -> generate(out, className, fields, dir, table) }
}

def generate(out, className, fields, dir, table) {
    packageName = findPackageName(dir)
    def domainPackageName = findDomainPackageName(dir)
    def servicePackageName = findServicePackageName(dir)
    def fastLowerClassName = toLowerCaseFirstOne(className)
    def userName = System.getProperty( "user.name")
    def currentDate = currentDate()
    //读取表备注
    def tableComment = table.getComment()
    if(tableComment == null || tableComment == '') {
        tableComment = table.getName()
    }
    tableComment = new String(tableComment.getBytes("utf-8"),"gbk");
    if(packageName != "") out.println("package $packageName;\n")
    out.println(
            "\n" +
            "import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\n" +
            "import java.util.List;\n" +
            "import java.util.Arrays;\n" +
            "import lombok.RequiredArgsConstructor;\n" +
            "import org.springframework.security.access.prepost.PreAuthorize;\n" +
            "import org.springframework.beans.factory.annotation.Autowired;\n" +
            "import org.springframework.web.bind.annotation.GetMapping;\n" +
            "import org.springframework.web.bind.annotation.PostMapping;\n" +
            "import org.springframework.web.bind.annotation.PutMapping;\n" +
            "import org.springframework.web.bind.annotation.DeleteMapping;\n" +
            "import org.springframework.web.bind.annotation.PathVariable;\n" +
            "import org.springframework.web.bind.annotation.RequestBody;\n" +
            "import org.springframework.web.bind.annotation.RequestMapping;\n" +
            "import org.springframework.web.bind.annotation.RestController;\n" +
            "import ${domainPackageName}.${className};\n" +
            "import ${servicePackageName}.I${className}Service;\n" +
            "import com.ruoyi.common.utils.poi.ExcelUtil;\n" +
            "import com.ruoyi.common.core.page.TableDataInfo;\n" +
            "\n" +
            "/**\n" +
            " * ${tableComment}Controller\n" +
            " *\n" +
            " * @author ${userName}\n" +
            " * @date ${currentDate}\n" +
            " */\n" +
            "@RequiredArgsConstructor(onConstructor_ = @Autowired)\n" +
            "@RestController\n" +
            "@RequestMapping(\"/system/${fastLowerClassName}\" )\n" +
            "public class ${className}Controller extends BaseController {\n" +
            "\n" +
            "    private final I${className}Service i${className}Service;\n" +
            "\n" +
            "    /**\n" +
            "     * 查询${tableComment}列表\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:list')\")\n" +
            "    @GetMapping(\"/list\")\n" +
            "    public TableDataInfo list(${className} ${fastLowerClassName})\n" +
            "    {\n" +
            "        startPage();\n" +
            "        LambdaQueryWrapper<${className}> lqw = new LambdaQueryWrapper<${className}>();\n")

                fields.each() {
                    //字符串类型处理
                    if(it.type == "String") {
                        out.println("        if (StringUtils.isNotBlank(${fastLowerClassName}.get${it.name.capitalize()}())){\n" +
                                "            lqw.like(${className}::get${it.name.capitalize()} ,${fastLowerClassName}.get${it.name.capitalize()}());\n" +
                                "        }")
                    } else {
                        out.println("        if (${fastLowerClassName}.get${it.name.capitalize()}() != null){\n" +
                                "            lqw.eq(${className}::get${it.name.capitalize()} ,${fastLowerClassName}.get${it.name.capitalize()}());\n" +
                                "        }")
                    }
                }

            out.println("        List<${className}> list = i${className}Service.list(lqw);\n" +
            "        return getDataTable(list);\n" +
            "    }\n" +
            "\n" +
            "    /**\n" +
            "     * 导出${tableComment}列表\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:export')\" )\n" +
            "    @Log(title = \"${tableComment}\" , businessType = BusinessType.EXPORT)\n" +
            "    @GetMapping(\"/export\" )\n" +
            "    public R export(${className} ${fastLowerClassName}) {\n" +
            "        LambdaQueryWrapper<${className}> lqw = new LambdaQueryWrapper<${className}>(${fastLowerClassName});\n" +
            "        List<${className}> list = i${className}Service.list(lqw);\n" +
            "        ExcelUtil<${className}> util = new ExcelUtil<${className}>(${className}. class);\n" +
            "        return util.exportExcel(list, \"${fastLowerClassName}\" );\n" +
            "    }\n" +
            "\n" +
            "    /**\n" +
            "     * 获取${tableComment}详细信息\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:query')\" )\n" +
            "    @GetMapping(value = \"/{id}\" )\n" +
            "    public R getInfo(@PathVariable(\"id\" ) Long id) {\n" +
            "        return R.success(i${className}Service.getById(id));\n" +
            "    }\n" +
            "\n" +
            "    /**\n" +
            "     * 新增${tableComment}\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:add')\" )\n" +
            "    @Log(title = \"${tableComment}\" , businessType = BusinessType.INSERT)\n" +
            "    @PostMapping\n" +
            "    public R add(@RequestBody ${className} ${fastLowerClassName}) {\n" +
            "        return toAjax(i${className}Service.save(${fastLowerClassName}) ? 1 : 0);\n" +
            "    }\n" +
            "\n" +
            "    /**\n" +
            "     * 修改${tableComment}\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:edit')\" )\n" +
            "    @Log(title = \"${tableComment}\" , businessType = BusinessType.UPDATE)\n" +
            "    @PutMapping\n" +
            "    public R edit(@RequestBody ${className} ${fastLowerClassName}) {\n" +
            "        return toAjax(i${className}Service.updateById(${fastLowerClassName}) ? 1 : 0);\n" +
            "    }\n" +
            "\n" +
            "    /**\n" +
            "     * 删除${tableComment}\n" +
            "     */\n" +
            "    @PreAuthorize(\"@ss.hasPermi('system:${fastLowerClassName}:remove')\" )\n" +
            "    @Log(title = \"${tableComment}\" , businessType = BusinessType.DELETE)\n" +
            "    @DeleteMapping(\"/{ids}\" )\n" +
            "    public R remove(@PathVariable Long[] ids) {\n" +
            "        return toAjax(i${className}Service.removeByIds(Arrays.asList(ids)) ? 1 : 0);\n" +
            "    }\n" +
            "}")
//    out.println "package $packageName"
//    out.println ""
//    out.println ""
//    out.println "public class $className {"
//    out.println ""
//    fields.each() {
//        if (it.annos != "") out.println "  ${it.annos}"
//        out.println "  private ${it.type} ${it.name};"
//    }
//    out.println ""
//    fields.each() {
//        out.println ""
//        out.println "  public ${it.type} get${it.name.capitalize()}() {"
//        out.println "    return ${it.name};"
//        out.println "  }"
//        out.println ""
//        out.println "  public void set${it.name.capitalize()}(${it.type} ${it.name}) {"
//        out.println "    this.${it.name} = ${it.name};"
//        out.println "  }"
//        out.println ""
//    }
//    out.println "}"
}

def calcFields(table) {
    DasUtil.getColumns(table).reduce([]) { fields, col ->
        def spec = Case.LOWER.apply(col.getDataType().getSpecification())
        def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
        fields += [[
                           name : javaName(col.getName(), false),
                           type : typeStr,
                           comment: col.getComment(),
                           annos: ""]]
    }
}

def javaName(str, capitalize) {
    def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
            .collect { Case.LOWER.apply(it).capitalize() }
            .join("")
            .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
    capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

/**
 * 查找domain命名空间
 *
 * @param dir
 */
def findDomainPackageName(dir) {
    return findPackageName(new File(dir.getParent() + "/domain"))
}

/**
 * 查找service命名空间
 *
 * @param dir
 */
def findServicePackageName(dir) {
    return findPackageName(new File(dir.getParent() + "/service"))
}

/**
 * 查找指定目录现有的命名空间
 *
 * @param dir
 * @return
 */
def findPackageName(dir) {
    if(dir != null && dir.isDirectory()) {
        File[] files = dir.listFiles();
        if(files != null && files.length>0) {
            for (File item:files) {
                if(item.isFile()) {
                    List<String> lines = Files.readLines(item, StandardCharsets.UTF_8);
                    //查找命名空间
                    for (String line: lines) {
                        line = line.trim();
                        if(line.startsWith("package")) {
                            line = line.split(" ")[1];
                            line = line.replace(";", "")
                            line = line.trim();
                            return line;
                        }
                    }
                }
            }
        }
    }
    return ""
}

/**
 * 首字母小写
 * @param s
 * @return
 */
def toLowerCaseFirstOne(String s){
    if(Character.isLowerCase(s.charAt(0)))
        return s;
    else
        return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
}

/**
 * 获取当前时间
 * @return
 */
def currentDate() {
    Date d = new Date();
    System.out.println(d);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String dateNowStr = sdf.format(d);
    return dateNowStr;
}